#version 430 core

struct Particle {
	vec3 position;
	vec3 velocity;
    vec3 startVelocity;
    vec3 strength;
    vec4 color;
    float angle;
    float angularVelocity;
    float lifeTime;
    float livedTime;
    bool isActive;
    vec2 scale;
    float temp3;
    float temp4;
};

layout (binding = 0) uniform ParameterUBO {
    float deltaTime;
    vec3 boundingBoxVectorX;
    vec3 boundingBoxVectorY;
    vec3 boundingBoxVectorZ;
    vec3 boundingBoxPoint;
    float maxSpeed;
    vec3 emitterCenter;
    int totalCount;
    int indexToShoot;
}ubo;

layout(std430, binding = 1) buffer ParticleSSBOIn {
   Particle particlesIn[ ];
};
layout(std430, binding = 2) buffer ParticleSSBOOut {
   Particle particlesOut[ ];
};
layout (local_size_x = 1024, local_size_y = 1, local_size_z = 1) in;

float rand(vec2 co)
{
    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}

vec3 getRandPos(vec2 seed)
{
    return rand(seed)*ubo.boundingBoxVectorX +
    rand(seed + vec2(1.0, 0.0))*ubo.boundingBoxVectorY +
    rand(seed + vec2(0.0, 1.0))*ubo.boundingBoxVectorZ +
    ubo.boundingBoxPoint;
}


void main()
{
	uint index = gl_GlobalInvocationID.x; 
    Particle particleIn = particlesIn[index];
    vec2 seed = vec2(gl_GlobalInvocationID.xy);
    
    //particlesOut[index].temp = rand(seed);
    //particlesOut[index].temp2 =  rand(seed + vec2(1.0, 0.0));
    //particlesOut[index].temp3 =  rand(seed + vec2(0.0, 1.0));
    //particlesOut[index].temp4 = gl_GlobalInvocationID.w;
    
    
    if(ubo.indexToShoot >= index) {
        if(particleIn.isActive == false) particleIn.position = getRandPos(seed);
        particleIn.isActive = true;
    }
    
    particlesOut[index].startVelocity = particleIn.startVelocity;
    particlesOut[index].isActive = particleIn.isActive;
    particlesOut[index].color = vec4(0.0f, particlesOut[index].scale.y, 0.0f, 1.0f);

    if(particlesOut[index].isActive == true){
        particlesOut[index].livedTime = particleIn.livedTime + ubo.deltaTime;
        particlesOut[index].position = particleIn.position + particleIn.velocity.xyz * ubo.deltaTime;
        particlesOut[index].velocity = particleIn.velocity + particleIn.strength;
        if(particlesOut[index].velocity.length() > ubo.maxSpeed){
            particlesOut[index].velocity = normalize(particlesOut[index].velocity) * ubo.maxSpeed;
        }
        particlesOut[index].angle = particleIn.angle + particleIn.angularVelocity * ubo.deltaTime;
        particlesOut[index].lifeTime = particleIn.lifeTime;
    }

    if(particlesOut[index].livedTime > particlesOut[index].lifeTime){
        particlesOut[index].velocity = particlesOut[index].startVelocity;
        particlesOut[index].position = getRandPos(seed);
        particlesOut[index].livedTime = 0.0f;
    }
}